<template>
  <Form :model="formState" ref="formRef">
    <Row :gutter="24" :style="{ height: '50px' }">
      <Col :span="7">
        <FormItem
          name="timeRange"
          label="时间范围"
          :rules="[{ required: true, message: '请选择时间', trigger: 'change' }]"
        >
          <RangePicker
            v-model:value="formState.timeRange"
            name="timeRange"
            :format="format"
            :show-time="showTimeRef"
            :ranges="timeRangeOptions"
            :disabledDate="disabledDate"
            @change="onTimeRangeChange"
            @calendarChange="onCalendarChange"
            @openChange="onOpenChange"
            style="width: 420px"
          ></RangePicker>
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem name="service" label="服务">
          <Select
            v-model:value="formState.service"
            placeholder="请选择服务"
            :options="serviceOptions"
            :allowClear="true"
            @change="onServiceChange"
            style="width: 230px"
          >
          </Select>
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem name="endpoint" label="端点">
          <Select
            v-model:value="formState.endpoint"
            placeholder="请选择端点"
            :options="endpointOptions"
            :allowClear="true"
            :disabled="formDisabled.others"
            style="width: 240px"
          >
          </Select>
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem name="instance" label="实例">
          <Select
            v-model:value="formState.instance"
            placeholder="请选择实例"
            :options="instanceOptions"
            :allowClear="true"
            :disabled="formDisabled.others"
            style="width: 240px"
          >
          </Select>
        </FormItem>
      </Col>
    </Row>
    <Row :gutter="24" :style="{ height: '30px' }">
      <Col :span="7">
        <FormItem label="标记">
          <Select
            v-model:value="currentTagKey"
            style="width: 90px"
            :options="tagKeyOptions"
            :disabled="formDisabled.tags"
            @change="tagKeyChange"
          ></Select
          >=<Select
            v-model:value="currentTagValue"
            style="width: 90px"
            :options="tagValueOptions"
            :disabled="formDisabled.tags"
            @change="tagValueChange"
          ></Select>
          <Select
            v-if="show"
            v-model:value="tagArr"
            mode="multiple"
            :maxTagTextLength="6"
            :maxTagCount="2"
            style="width: 260px"
            :options="tagArrList"
            :disabled="formDisabled.tags"
            :allowClear="true"
            @change="finalTagChange"
          ></Select>
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem label="持续时间">
          <InputNumber
            v-model:value="formState.min"
            :formatter="(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
            :parser="(value) => value.replace(/\$\s?|(,*)/g, '')"
            placeholder="最小"
            style="width: 96px"
          />~<InputNumber
            v-model:value="formState.max"
            :formatter="(value) => `${value}`.replace(/\B(?=(\d{3})+(?!\d))/g, ',')"
            :parser="(value) => value.replace(/\$\s?|(,*)/g, '')"
            placeholder="最大"
            style="width: 96px"
          />
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem name="traceState" label="状态">
          <Select
            v-model:value="formState.traceState"
            placeholder="请选择状态"
            :options="stateOptions"
            :allowClear="true"
            style="width: 240px"
          >
          </Select>
        </FormItem>
      </Col>
      <Col :span="4">
        <FormItem name="traceId" label="追踪ID">
          <Input v-model:value="formState.traceId" placeholder="请输入追踪id" :allowClear="true" style="width: 230px">
          </Input>
        </FormItem>
      </Col>

      <div class="btn-wrapper">
        <Tooltip title="查询">
          <Button type="primary" @click="search" shape="circle"
            ><template #icon><SearchOutlined /></template
          ></Button>
        </Tooltip>
        <Tooltip title="重置">
          <Button style="margin-left: 10px" @click="reset" shape="circle"
            ><template #icon><RedoOutlined /></template
          ></Button>
        </Tooltip>
      </div>
    </Row>
  </Form>
</template>

<script setup lang="ts">
import { reactive, ref, watch } from 'vue';
import moment from 'moment';
import { Button, Col, Form, Tooltip, FormItem, Select, RangePicker, Row, Input, InputNumber } from 'ant-design-vue';
import { SearchOutlined, RedoOutlined } from '@ant-design/icons-vue';
import dayjs, { Dayjs } from 'dayjs';
import {
  getEndpoint,
  getInstanceAttributes,
  getService,
  getTagValue,
} from '/@/api/maintenance-center/skywalking/trace/trace';
import { TagItem } from '/@/api/maintenance-center/skywalking/trace/model/traceModel';

const formRef = ref();
const showTimeRef = ref(true);
const formState = reactive<Record<string, any>>({
  service: undefined,
  endpoint: undefined,
  instance: undefined,
  traceState: undefined,
  traceId: undefined,
  tag: undefined,
  min: undefined,
  max: undefined,
  timeRange: null,
});
const formDisabled = reactive({
  others: true,
  tags: true,
});
const endpointOptions = ref<any[]>([]);
const instanceOptions = ref<any[]>([]);
const serviceOptions = ref<any[]>([]);
const tagValueOptions = ref<any[]>([]);
const tagKeyOptions = ref([
  { label: 'db.instance', value: 'db.instance' },
  { label: 'mq.topic', value: 'mq.topic' },
  { label: 'http.status_code', value: 'http.status_code' },
  { label: 'db.type', value: 'db.type' },
  { label: 'http.method', value: 'http.method' },
  { label: 'mq.broker', value: 'mq.broker' },
]);
const stateOptions = ref([
  { label: 'SUCCESS', value: 'SUCCESS' },
  { label: 'ERROR', value: 'ERROR' },
]);

const timeRangeOptions = {
  最近15分钟: [dayjs().subtract(15, 'minute'), dayjs()],
  最近30分钟: [dayjs().subtract(30, 'minute'), dayjs()],
  最近1小时: [dayjs().subtract(1, 'hour'), dayjs()],
  最近1天: [dayjs().subtract(1, 'day'), dayjs()],
  最近1周: [dayjs().subtract(1, 'week'), dayjs()],
  最近1月: [dayjs().subtract(1, 'month'), dayjs()],
  最近2月: [dayjs().subtract(2, 'month'), dayjs()],
};
const format = ref<string>('YYYY-MM-DD HH:mm:ss');

const stepFormatMap = {
  SECOND: 'YYYY-MM-DD HHmmss',
  MINUTE: 'YYYY-MM-DD HHmm',
  HOUR: 'YYYY-MM-DD HH',
  DAY: 'YYYY-MM-DD',
  MONTH: 'YYYY-MM',
};

let disabledCurrent: any = null;
let isHandOperated = false;
function onOpenChange(status: boolean) {
  if (status) {
    disabledCurrent = formState.timeRange;
  } else {
    disabledCurrent = null;
  }
}

function onCalendarChange(dates: [Dayjs, Dayjs]) {
  if (dates && dates[0] && dates[1]) {
    return;
  }
  if (dates !== null) {
    isHandOperated = true;
    disabledCurrent = dates;
    return;
  }
}

function disabledDate(current: Dayjs) {
  if (!disabledCurrent) {
    return false;
  }
  if (disabledCurrent[0] && disabledCurrent[1]) {
    return (
      current && (current > disabledCurrent[0].add(2, 'month') || current < disabledCurrent[1].subtract(2, 'month'))
    );
  }
  if (disabledCurrent[0]) {
    return current && current > disabledCurrent[0].add(2, 'month');
  }
  if (disabledCurrent[1]) {
    return current && current < disabledCurrent[1].subtract(2, 'month');
  }
}

let durationParam = {
  start: '',
  end: '',
  step: '',
};

function processDuration(startTime: moment.Moment, endTime: moment.Moment, step: string) {
  if (startTime.second() !== endTime.second() && !isHandOperated) {
    step = 'SECOND';
    durationParam.start = startTime.format(stepFormatMap.SECOND);
    durationParam.end = endTime.format(stepFormatMap.SECOND);
  } else if (startTime.minute() !== endTime.minute() && !isHandOperated) {
    step = 'MINUTE';
    durationParam.start = startTime.format(stepFormatMap.MINUTE);
    durationParam.end = endTime.format(stepFormatMap.MINUTE);
  } else if (startTime.hour() !== endTime.hour()) {
    step = 'HOUR';
    durationParam.start = startTime.format(stepFormatMap.HOUR);
    durationParam.end = endTime.format(stepFormatMap.HOUR);
  } else if (startTime.day() !== endTime.day()) {
    step = 'DAY';
    durationParam.start = startTime.format(stepFormatMap.DAY);
    durationParam.end = endTime.format(stepFormatMap.DAY);
  } else {
    step = 'DAY';
    durationParam.start = startTime.format(stepFormatMap.DAY);
    durationParam.end = endTime.format(stepFormatMap.DAY);
  }

  durationParam.step = step;
  return durationParam;
}
const show = ref(false);
interface Option {
  label: string;
  value: string;
}
const tagArr = ref<Option[]>([]);
const tagArrList = ref<Option[]>([]);
const currentTagKey = ref();
const currentTagValue = ref();

const tagKeyChange = async (data) => {
  currentTagValue.value = undefined;
  let valueParam = {
    duration: durationParam,
    tagKey: data,
  };
  if (data) {
    tagValueOptions.value = await getTagValue(valueParam);
  }
};
let finalTags: TagItem[] = [];
const tagValueChange = (data) => {
  if (data) {
    finalTags = [];
    show.value = true;
    let item = currentTagKey.value + '=' + currentTagValue.value;
    tagArr.value.push({ label: item, value: item });
    tagArrList.value.push({ label: item, value: item });
    tagArr.value.forEach((item) => {
      let key = '';
      let value = '';
      if (item.label) {
        key = item.label.split('=')[0];
        value = item.label.split('=')[1];
      } else {
        key = item.split('=')[0];
        value = item.split('=')[1];
      }
      finalTags.push({ key, value });
    });
  }
};

const finalTagChange = (value: string[]) => {
  finalTags = [];
  value.forEach((item) => {
    let key = item.split('=')[0];
    let value = item.split('=')[1];
    finalTags.push({ key, value });
    finalTags = [...new Set(finalTags)];
  });
};

watch(tagArrList, () => {
  if (tagArrList.value.length == 0) {
    show.value = false;
  }
});

// 获取服务列表
let serviceParams = {
  duration: durationParam,
  keyword: '',
};
const getServiceData = async () => {
  serviceOptions.value = await getService(serviceParams);
};

let navParams = {
  endpointId: formState.endpoint,
  maxTraceDuration: formState.max,
  minTraceDuration: formState.min,
  paging: { pageNum: 1, pageSize: 10 },
  queryDuration: durationParam,
  queryOrder: 'BY_START_TIME',
  serviceId: formState.service,
  serviceInstanceId: formState.instance,
  tags: finalTags,
  traceId: formState.traceId,
  traceState: formState.traceState,
};
// 清空formState
const clearFormState = (justChangeService?) => {
  if (justChangeService == true) {
    formState.endpoint = undefined;
    formState.instance = undefined;
    formState.traceState = undefined;
    formState.traceId = undefined;
    formState.min = undefined;
    formState.max = undefined;
    tagArr.value = [];
    currentTagKey.value = [];
    currentTagValue.value = [];
    tagArrList.value = [];
  } else {
    formState.service = undefined;
    formState.endpoint = undefined;
    formState.instance = undefined;
    formState.traceState = undefined;
    formState.traceId = undefined;
    formState.min = undefined;
    formState.max = undefined;
    tagArr.value = [];
    currentTagKey.value = [];
    currentTagValue.value = [];
    tagArrList.value = [];
  }
};
// 刷新当前navParams
const refreshNavParams = () => {
  navParams = {
    endpointId: formState.endpoint,
    maxTraceDuration: formState.max,
    minTraceDuration: formState.min,
    paging: { pageNum: 1, pageSize: 10 },
    queryDuration: durationParam,
    queryOrder: 'BY_START_TIME',
    serviceId: formState.service,
    serviceInstanceId: formState.instance,
    tags: finalTags,
    traceId: formState.traceId,
    traceState: formState.traceState,
  };
  if (!formState.traceState) {
    navParams.traceState = 'ALL';
  }
};
const emit = defineEmits(['get', 'clearNav']);
const onServiceChange = async (data) => {
  clearFormState(true);
  refreshNavParams();
  if (data !== null && data != '' && data != undefined) {
    let endpointParams = {
      serviceId: data,
      keyword: '',
      limit: 100,
    };
    endpointOptions.value = await getEndpoint(endpointParams);

    let instanceParams = {
      serviceId: data,
      duration: durationParam,
    };
    instanceOptions.value = await getInstanceAttributes(instanceParams);

    formDisabled.others = false;
    refreshNavParams();
    emit('get', navParams);
  } else {
    clearFormState();
    formDisabled.others = true;
    refreshNavParams();
    if (formState.timeRange !== undefined && formState.timeRange !== null) {
      emit('get', navParams);
    } else {
      emit('clearNav');
    }
  }
};
// 时间范围选择好
const onTimeRangeChange = (data) => {
  clearFormState();
  refreshNavParams();
  if (data !== null && data != undefined && data.length != 0) {
    let startTime = data[0];
    let endTime = data[1];
    let step = '';
    durationParam = processDuration(startTime, endTime, step);
    serviceParams.duration = durationParam;
    formDisabled.tags = false;
    getServiceData();
  } else {
    formState.service = undefined;
    formDisabled.tags = true;
    onServiceChange(null);
  }
  isHandOperated = false;
};

// 提交表单参数
const search = async () => {
  formRef.value.validate();
  if (formState.timeRange !== null) {
    refreshNavParams();
    emit('get', navParams);
  }
};

// 清空表单参数
const reset = () => {
  formRef.value.clearValidate();
  formState.timeRange = undefined;
  onTimeRangeChange(null);
};
</script>
<style lang="less">
.btn-wrapper {
  display: flex;
  justify-content: flex-end;
  flex: 1;
  padding: 0px 20px;
}
</style>
